home *** CD-ROM | disk | FTP | other *** search
- ; BARRIER.ASM
- ;
- ; This sample program demonstrates how to use the Standard Library's
- ; semaphore objects to synchronize several processes at a barrier.
- ; This program is similar to the MULTIDOS.ASM program insofar as the
- ; background processes all print a set of strings. However, rather than
- ; using an inelegant delay loop to synchronize the foreground and background
- ; processes, this code uses barrier synchronization to achieve this.
-
- .xlist
- include stdlib.a
- includelib stdlib.lib
- .list
-
-
- dseg segment para public 'data'
-
- BarrierSemaph semaphore {0} ;Must init SemaCnt to zero.
- DOSsmaph semaphore {}
-
- ; Macros to wait and release the DOS semaphore:
-
- DOSWait macro
- push es
- push di
- lesi DOSsmaph
- WaitSemaph
- pop di
- pop es
- endm
-
- DOSRls macro
- push es
- push di
- lesi DOSsmaph
- RlsSemaph
- pop di
- pop es
- endm
-
-
- ; Macro to synchronize on a barrier:
-
- Barrier macro Wait4Cnt
- local AllHere, AllDone
- cmp es:[di].semaphore.SemaCnt, -(Wait4Cnt-1)
- jle AllHere
- WaitSemaph
- cmp es:[di].semaphore.SemaCnt, 0
- jge AllDone
- AllHere: RlsSemaph
- AllDone:
- endm
-
-
-
-
- ; PCBs for our background processes:
-
- BkgndPCB2 pcb {0,offset EndStk2, seg EndStk2}
- BkgndPCB3 pcb {0,offset EndStk3, seg EndStk3}
-
- ; Data the foreground and background processes print:
-
- StrPtrs1 dword str1_a, str1_b, str1_c, str1_d, str1_e, str1_f
- dword str1_g, str1_h, str1_i, str1_j, str1_k, str1_l
- dword 0
-
- str1_a byte "Foreground: string 'a'",cr,lf,0
- str1_b byte "Foreground: string 'b'",cr,lf,0
- str1_c byte "Foreground: string 'c'",cr,lf,0
- str1_d byte "Foreground: string 'd'",cr,lf,0
- str1_e byte "Foreground: string 'e'",cr,lf,0
- str1_f byte "Foreground: string 'f'",cr,lf,0
- str1_g byte "Foreground: string 'g'",cr,lf,0
- str1_h byte "Foreground: string 'h'",cr,lf,0
- str1_i byte "Foreground: string 'i'",cr,lf,0
- str1_j byte "Foreground: string 'j'",cr,lf,0
- str1_k byte "Foreground: string 'k'",cr,lf,0
- str1_l byte "Foreground: string 'l'",cr,lf,0
-
- StrPtrs2 dword str2_a, str2_b, str2_c, str2_d, str2_e, str2_f
- dword str2_g, str2_h, str2_i
- dword 0
-
- str2_a byte "Background 1: string 'a'",cr,lf,0
- str2_b byte "Background 1: string 'b'",cr,lf,0
- str2_c byte "Background 1: string 'c'",cr,lf,0
- str2_d byte "Background 1: string 'd'",cr,lf,0
- str2_e byte "Background 1: string 'e'",cr,lf,0
- str2_f byte "Background 1: string 'f'",cr,lf,0
- str2_g byte "Background 1: string 'g'",cr,lf,0
- str2_h byte "Background 1: string 'h'",cr,lf,0
- str2_i byte "Background 1: string 'i'",cr,lf,0
-
- StrPtrs3 dword str3_a, str3_b, str3_c, str3_d, str3_e, str3_f
- dword str3_g, str3_h, str3_i
- dword 0
-
- str3_a byte "Background 2: string 'j'",cr,lf,0
- str3_b byte "Background 2: string 'k'",cr,lf,0
- str3_c byte "Background 2: string 'l'",cr,lf,0
- str3_d byte "Background 2: string 'm'",cr,lf,0
- str3_e byte "Background 2: string 'n'",cr,lf,0
- str3_f byte "Background 2: string 'o'",cr,lf,0
- str3_g byte "Background 2: string 'p'",cr,lf,0
- str3_h byte "Background 2: string 'q'",cr,lf,0
- str3_i byte "Background 2: string 'r'",cr,lf,0
-
- dseg ends
-
- cseg segment para public 'code'
- assume cs:cseg, ds:dseg
-
- ; A replacement critical error handler. This routine calls prcsquit
- ; if the user decides to abort the program.
-
-
- CritErrMsg byte cr,lf
- byte "DOS Critical Error!",cr,lf
- byte "A)bort, R)etry, I)gnore, F)ail? $"
-
- MyInt24 proc far
- push dx
- push ds
- push ax
-
- push cs
- pop ds
- Int24Lp: lea dx, CritErrMsg
- mov ah, 9 ;DOS print string call.
- int 21h
-
- mov ah, 1 ;DOS read character call.
- int 21h
- and al, 5Fh ;Convert l.c. -> u.c.
-
- cmp al, 'I' ;Ignore?
- jne NotIgnore
- pop ax
- mov al, 0
- jmp Quit24
-
- NotIgnore: cmp al, 'r' ;Retry?
- jne NotRetry
- pop ax
- mov al, 1
- jmp Quit24
-
- NotRetry: cmp al, 'A' ;Abort?
- jne NotAbort
- prcsquit ;If quitting, fix INT 8.
- pop ax
- mov al, 2
- jmp Quit24
-
- NotAbort: cmp al, 'F'
- jne BadChar
- pop ax
- mov al, 3
- Quit24: pop ds
- pop dx
- iret
-
- BadChar: mov ah, 2
- mov dl, 7 ;Bell character
- jmp Int24Lp
- MyInt24 endp
-
-
-
- ; We will simply disable INT 23h (the break exception).
-
- MyInt23 proc far
- iret
- MyInt23 endp
-
-
-
- ; This background processes call DOS to print several strings to the
- ; screen. In the meantime, the foreground process is also printing
- ; strings to the screen. To prevent reentry, or at least a jumble of
- ; characters on the screen, this code uses semaphores to protect the
- ; DOS calls. Therefore, each process will print one complete line
- ; then release the semaphore. If the other process is waiting it will
- ; print its line.
-
- BackGround1 proc
- mov ax, dseg
- mov ds, ax
-
- ; Wait for everyone else to get ready:
-
- lesi BarrierSemaph
- barrier 3
-
- ; Okay, start printing the strings:
-
- lea bx, StrPtrs2 ;Array of str ptrs.
- PrintLoop: cmp word ptr [bx+2], 0 ;At end of pointers?
- je BkGndDone
- les di, [bx] ;Get string to print.
- DOSWait
- puts ;Calls DOS to print string.
- DOSRls
- add bx, 4 ;Point at next str ptr.
- jmp PrintLoop
-
- BkGndDone: die
- BackGround1 endp
-
-
- BackGround2 proc
- mov ax, dseg
- mov ds, ax
-
- lesi BarrierSemaph
- barrier 3
-
- lea bx, StrPtrs3 ;Array of str ptrs.
- PrintLoop: cmp word ptr [bx+2], 0 ;At end of pointers?
- je BkGndDone
- les di, [bx] ;Get string to print.
- DOSWait
- puts ;Calls DOS to print string.
- DOSRls
- add bx, 4 ;Point at next str ptr.
- jmp PrintLoop
-
- BkGndDone: die
- BackGround2 endp
-
-
-
- Main proc
- mov ax, dseg
- mov ds, ax
- mov es, ax
- meminit
-
-
- ; Initialize the INT 23h and INT 24h exception handler vectors.
-
- mov ax, 0
- mov es, ax
- mov word ptr es:[24h*4], offset MyInt24
- mov es:[24h*4 + 2], cs
- mov word ptr es:[23h*4], offset MyInt23
- mov es:[23h*4 + 2], cs
-
- prcsinit ;Start multitasking system.
-
- ; Start the first background process:
-
- lesi BkgndPCB2 ;Fire up a new process
- fork
- test ax, ax ;Parent's return?
- je StartBG2
- jmp BackGround1 ;Go do backgroun stuff.
-
- ; Start the second background process:
-
- StartBG2: lesi BkgndPCB3 ;Fire up a new process
- fork
- test ax, ax ;Parent's return?
- je ParentPrcs
- jmp BackGround2 ;Go do backgroun stuff.
-
- ; The parent process will print a bunch of strings at the same time
- ; the background process is doing this. We'll use the DOS semaphore
- ; to protect the call to DOS that PUTS makes.
-
- ParentPrcs: lesi BarrierSemaph
- barrier 3
-
- lea bx, StrPtrs1 ;Array of str ptrs.
- PrintLoop: cmp word ptr [bx+2], 0 ;At end of pointers?
- je ForeGndDone
- les di, [bx] ;Get string to print.
- DOSWait
- puts ;Calls DOS to print string.
- DOSRls
- add bx, 4 ;Point at next str ptr.
- jmp PrintLoop
-
- ForeGndDone: prcsquit
-
- Quit: ExitPgm ;DOS macro to quit program.
- Main endp
-
- cseg ends
-
- sseg segment para stack 'stack'
-
- ; Here are the stacks for the background processes we start
-
- stk2 byte 1024 dup (?)
- EndStk2 word ?
-
- stk3 byte 1024 dup (?)
- EndStk3 word ?
-
- ;Here's the stack for the main program/foreground process.
-
- stk byte 1024 dup (?)
- sseg ends
-
- zzzzzzseg segment para public 'zzzzzz'
- LastBytes db 16 dup (?)
- zzzzzzseg ends
- end Main
-